//
//  Board.m
//  INFSWA02
//
//  Created by Justin van Grootveld on 9/21/11.
//  Copyright 2011 Justinform. All rights reserved.
//

#import "Board.h"
#import "Square.h"
#import "Piece.h"
#import "Player.h"
#import "NoState.h"
#import "ActionState.h"
#import "CircularBufferController.h"
#import "Command.h"

@interface Board(local)
- (void)initGrid;
@end

@implementation Board

@synthesize mainViewController = _mainViewController, size = _size, player1 = _player1, player2 = _player2, currentPlayer = _currentPlayer, grid = _grid, currentState, noState, actionState;

- (id)initWithS:(NSInteger)size
{
    self = [super init];
    if (self) 
    {
        _player1 = nil;
        _player2 = nil;
        _currentPlayer = nil;
        _size = size;
        _grid = [[NSMutableArray alloc] initWithCapacity:size];
        [self initGrid];
        
        //States
        [self setCurrentState:[NoState new]];
        [self setNoState:[NoState new]];
        [self setActionState:[ActionState new]];
        
        _circularBuffer = [[CircularBufferController alloc] initWithBufferSize:3];
    }
    
    return self;
}

- (void)updateButtonTitles
{
    for (NSMutableArray *row in _grid)
        for (Square *square in row)
            [square setButtonTitle];
}

#pragma mark - local- (void)initGrids
- (void)initGrid
{
    for(int y=0; y < _size; y++)
    {
        NSMutableArray *row = [[NSMutableArray alloc] initWithCapacity:_grid.count];
        
        for(int x=0; x < _size; x++)
            [row addObject:[[Square alloc] initWithBoard:self andLocation:NSMakePoint(x, y)]];
    
        [_grid addObject:row];
    }
}

#pragma mark - methods
- (BOOL)setPiece: (Piece *)piece atLocationX:(NSInteger)x andY:(NSInteger)y
{
    return [[self squareAtLocationX:x andY:y] setPiece:piece];
}

- (Square *)squareAtLocationX:(NSInteger)x andY:(NSInteger)y
{
    if(x < 0 || y < 0 || x >= _size || y >= _size) return nil;
    
    return (Square *)[[_grid objectAtIndex:y] objectAtIndex:x];
}

- (Square *)squareForPiece:(Piece *)piece
{
    for(NSMutableArray *row in _grid)
    {
        for(Square *square in row)
        {
            if ([square piece] == piece) return square;
        }
    }
    
    return nil;
}

- (void)initPlayersWithNames:(NSString *)player1Name andPlayer2:(NSString *)player2Name
{
    _player1 = [[Player alloc] initWithUsername:player1Name AndIdentifier:1];
    _player2 = [[Player alloc] initWithUsername:player2Name AndIdentifier:2];
    _currentPlayer = _player1;
}

- (BOOL)isCurrentPlayer:(Player *)player
{
    return [player isCurrentPlayer:_currentPlayer];
}

#pragma mark - Moving methods

- (void)movePiece:(Piece *)piece toSquare:(Square *)square
{
    Square *originalSquare = [self squareForPiece:piece];
    
    [self setPiece:piece atLocationX:square.location.x andY:square.location.y];
    [originalSquare removePiece];
}

#pragma mark - Printing methods

- (void)print
{
    //start
    NSString *printString = @"\n|";
    
    for(int i=0; i < _size; i++)
        printString = [printString stringByAppendingString:@"---|"];
    
    
    //board
    for(NSMutableArray *row in _grid)
    {
        printString = [printString stringByAppendingString:@"\n|"];
        
        for(Square *square in row)
        {
            NSString *code = @"---";
            if([square hasPiece])
                code = [[square piece] printCode];
                
                printString = [printString stringByAppendingFormat:@"%@|", code];
            // NSLog(@"%d-%d", (int)[square location].x, (int)[square location].y);
        }
        
        printString = [printString stringByAppendingString:@"\n|"];
        
        for(int i=0; i < _size; i++)
            printString = [printString stringByAppendingString:@"---|"];
    }
    
     NSLog(@"%@", printString);
}

- (void)printLocations
{
    //start
    NSString *printString = @"\n|";
    
    for(int i=0; i < _size; i++)
        printString = [printString stringByAppendingString:@"---|"];
    
    
    //board
    for(NSMutableArray *row in _grid)
    {
        printString = [printString stringByAppendingString:@"\n|"];
        
        for(Square *square in row)
        {
            
            printString = [printString stringByAppendingFormat:@"%d-%d|", (int)[square location].x, (int)[square location].y];
            // NSLog(@"%d-%d", (int)[square location].x, (int)[square location].y);
        }
        
        printString = [printString stringByAppendingString:@"\n|"];
        
        for(int i=0; i < _size; i++)
            printString = [printString stringByAppendingString:@"---|"];
    }
    
    NSLog(@"%@", printString);
}

#pragma mark - save/load
- (void)saveState:(Command *)command;
{
    [_circularBuffer enqueueObject:command];
    NSLog(@"saved state");
    //[_circularBuffer print];
}

- (void)loadState
{
    //[_circularBuffer print];
    
    Command *command = [_circularBuffer dequeue];
    
    if([command isKindOfClass:[Command class]]) 
    {
        NSLog(@"undo");
        [command undo];
    }
    else
    {
        NSLog(@"There is no saved state");
    }
    
    [self updateButtonTitles];
}

- (BOOL)hasUndoState
{
    return [_circularBuffer hasObjects];
}

@end
